#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>

#define CR(Record, TYPE, Field)  ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))

typedef struct 
{
  UINTN Id;
  LIST_ENTRY Link;
} ITEM_LIST;

EFI_STATUS
EFIAPI
UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
{
  LIST_ENTRY ListHead;
  InitializeListHead(&ListHead);

  for (UINTN Index = 0; Index < 5; Index++) {
    ITEM_LIST *Item = AllocateZeroPool(sizeof(ITEM_LIST));
    if (Item == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    Item->Id = Index + 1;
    InsertTailList(&ListHead, &Item->Link);
  }

  Print(L"List contents:\n");
  LIST_ENTRY *CurrentEntry = GetFirstNode(&ListHead);
  while (!IsNull(&ListHead, CurrentEntry)) {
    ITEM_LIST *Item = CR(CurrentEntry, ITEM_LIST, Link);
    Print(L"Item Id: %u\n", Item->Id);
    CurrentEntry = GetNextNode(&ListHead, CurrentEntry);
  }

  // Free allocated memory
  Print(L"Removing all items from the list:\n");
  while (!IsNull(&ListHead, GetFirstNode(&ListHead))) {
    LIST_ENTRY *Entry = GetFirstNode(&ListHead);
    Print(L"Removing Item Id: %u\n", CR(Entry, ITEM_LIST, Link)->Id);
    RemoveEntryList(Entry);
    ITEM_LIST *Item = CR(Entry, ITEM_LIST, Link);
    FreePool(Item);
  }

  if (IsListEmpty(&ListHead)) {
    Print(L"All items removed, list is now empty.\n");
  } else {
    Print(L"List is not empty!\n");
  }

  return EFI_SUCCESS;
}